﻿using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Taschenrechner.Properties;

namespace Taschenrechner {
    internal class ArithmeticDispatcher {
        internal readonly Dictionary<ArithmeticOperator, Arithmetic> Operation = new Dictionary<ArithmeticOperator, Arithmetic>();

        internal ArithmeticDispatcher() {
            //dispatcher = new Dictionary<ArithmeticOperator,Arithmetic>();
            Operation.Add(ArithmeticOperator.add, new Add());
            Operation.Add(ArithmeticOperator.sub, new Sub());
            Operation.Add(ArithmeticOperator.multi, new Multi());
            Operation.Add(ArithmeticOperator.div, new Div());
        }
    }

    abstract internal class Arithmetic {
        internal abstract double Compute(Term term);
    }

    internal class Add : Arithmetic {
        internal override double Compute(Term term) {
            double result = term.Number1.Value + term.Number2.Value;
            if (Double.IsInfinity(result)) {
                throw new OverflowException(Resource.NumberArgumentExeptionOverflow);
            }
            return result;
        }
    }

    internal class Sub : Arithmetic {
        internal override double Compute(Term term) {
            double result = term.Number1.Value - term.Number2.Value;
            if (Double.IsInfinity(result)) {
                throw new OverflowException(Resource.NumberArgumentExeptionOverflow);
            }
            return result;
        }
    }

    internal class Multi : Arithmetic {
        internal override double Compute(Term term) {
            double result = term.Number1.Value * term.Number2.Value;
            if (Double.IsInfinity(result)) {
                throw new OverflowException(Resource.NumberArgumentExeptionOverflow);
            }
            return result;
        }
    }

    internal class Div : Arithmetic {
        internal override double Compute(Term term) {
            
            if (0.0 == term.Number2.Value) {
                throw new DivideByZeroException(Resource.DevideByZeroException);
            }

            double result = term.Number1.Value / term.Number2.Value;

            if (Double.IsInfinity(result)) {
                throw new OverflowException(Resource.NumberArgumentExeptionOverflow);
            }
            return result;
        }
    }
}